<template>
    <a-card>
        <a-form layout="inline" style="width: 100%;" :model="entity">
            <a-form-item label="项目路径" style="width: 100%;">
                <a-input v-model:value="entity.projectPath" />
            </a-form-item>
        </a-form>
        <a-divider />
        <a-form layout="inline" style="width: 100%;" :model="entity">
            <a-form-item label="实体名">
                <a-input v-model:value="entity.name" />
            </a-form-item>
            <a-form-item label="类名">
                <a-input v-model:value="entity.className" />
            </a-form-item>
            <a-form-item label="对象名">
                <a-input v-model:value="entity.objectName" />
            </a-form-item>
            <a-form-item label="相对包路径">
                <a-input v-model:value="entity.relativePackage" />
            </a-form-item>
        </a-form>
        <a-divider />
        <div class="code_layer">
            <a-form layout="inline" style="width: 100%;" :model="entityParam">
                <a-form-item>
                    <a-checkbox v-model:checked="entitySelected">Entity 层</a-checkbox>
                </a-form-item>
                <a-form-item label="基础包">
                    <a-input
                        v-model:value="entityParam.entityBasePackage"
                        :disabled="!entitySelected"
                    />
                </a-form-item>
                <a-form-item label="相对包路径">
                    <a-input
                        v-model:value="entityParam.relativePackage"
                        :disabled="!entitySelected"
                    />
                </a-form-item>
                <a-form-item label="类名前缀">
                    <a-input v-model:value="entityParam.classPrefix" :disabled="!entitySelected" />
                </a-form-item>
            </a-form>
            <a-form layout="inline" style="width: 100%;" :model="daoParam">
                <a-form-item>
                    <a-checkbox v-model:checked="daoSelected">Dao 层</a-checkbox>
                </a-form-item>
                <a-form-item label="基础包">
                    <a-input v-model:value="daoParam.daoBasePackage" :disabled="!daoSelected" />
                </a-form-item>
                <a-form-item label="相对包路径">
                    <a-input v-model:value="daoParam.relativePackage" :disabled="!daoSelected" />
                </a-form-item>
                <a-form-item label="类名前缀">
                    <a-input v-model:value="daoParam.classPrefix" :disabled="!daoSelected" />
                </a-form-item>
                <a-form-item label="Entity基础包">
                    <a-input v-model:value="daoParam.entityBasePackage" :disabled="!daoSelected" />
                </a-form-item>
            </a-form>
            <a-form layout="inline" style="width: 100%;" :model="modelParam">
                <a-form-item>
                    <a-checkbox v-model:checked="modelSelected">Model 层</a-checkbox>
                </a-form-item>
                <a-form-item label="基础包">
                    <a-input
                        v-model:value="modelParam.modelBasePackage"
                        :disabled="!modelSelected"
                    />
                </a-form-item>
                <a-form-item label="相对包路径">
                    <a-input v-model:value="modelParam.relativePackage" :disabled="!modelSelected" />
                </a-form-item>
                <a-form-item label="类名前缀">
                    <a-input v-model:value="modelParam.classPrefix" :disabled="!modelSelected" />
                </a-form-item>
                <a-form-item label="对象名前缀">
                    <a-input v-model:value="modelParam.objectPrefix" :disabled="!modelSelected" />
                </a-form-item>
                <a-form-item label="Entity基础包">
                    <a-input
                        v-model:value="modelParam.entityBasePackage"
                        :disabled="!modelSelected"
                    />
                </a-form-item>
            </a-form>
            <a-form layout="inline" style="width: 100%;" :model="managerParam">
                <a-form-item>
                    <a-checkbox v-model:checked="managerSelected">Manager 层</a-checkbox>
                </a-form-item>
                <a-form-item label="基础包">
                    <a-input
                        v-model:value="managerParam.managerBasePackage"
                        :disabled="!managerSelected"
                    />
                </a-form-item>
                <a-form-item label="相对包路径">
                    <a-input
                        v-model:value="managerParam.relativePackage"
                        :disabled="!managerSelected"
                    />
                </a-form-item>
                <a-form-item label="类名前缀">
                    <a-input v-model:value="managerParam.classPrefix" :disabled="!managerSelected" />
                </a-form-item>
                <a-form-item label="对象名前缀">
                    <a-input
                        v-model:value="managerParam.objectPrefix"
                        :disabled="!managerSelected"
                    />
                </a-form-item>
                <a-form-item label="Dao基础包">
                    <a-input
                        v-model:value="managerParam.daoBasePackage"
                        :disabled="!managerSelected"
                    />
                </a-form-item>
            </a-form>
            <a-form layout="inline" style="width: 100%;" :model="serviceParam">
                <a-form-item>
                    <a-checkbox v-model:checked="serviceSelected">Service 层</a-checkbox>
                </a-form-item>
                <a-form-item label="基础包">
                    <a-input
                        v-model:value="serviceParam.serviceBasePackage"
                        :disabled="!serviceSelected"
                    />
                </a-form-item>
                <a-form-item label="相对包路径">
                    <a-input
                        v-model:value="serviceParam.relativePackage"
                        :disabled="!serviceSelected"
                    />
                </a-form-item>
                <a-form-item label="类名前缀">
                    <a-input v-model:value="serviceParam.classPrefix" :disabled="!serviceSelected" />
                </a-form-item>
                <a-form-item label="对象名前缀">
                    <a-input
                        v-model:value="serviceParam.objectPrefix"
                        :disabled="!serviceSelected"
                    />
                </a-form-item>
                <a-form-item label="Entity基础包">
                    <a-input
                        v-model:value="serviceParam.entityBasePackage"
                        :disabled="!serviceSelected"
                    />
                </a-form-item>
                <a-form-item label="Dao基础包">
                    <a-input
                        v-model:value="serviceParam.daoBasePackage"
                        :disabled="!serviceSelected"
                    />
                </a-form-item>
                <a-form-item label="Model基础包">
                    <a-input
                        v-model:value="serviceParam.modelBasePackage"
                        :disabled="!serviceSelected"
                    />
                </a-form-item>
            </a-form>
            <a-form layout="inline" style="width: 100%;" :model="controllerParam">
                <a-form-item>
                    <a-checkbox v-model:checked="controllerSelcted">Controller 层</a-checkbox>
                </a-form-item>
                <a-form-item label="基础包">
                    <a-input
                        v-model:value="controllerParam.controllerBasePackage"
                        :disabled="!controllerSelcted"
                    />
                </a-form-item>
                <a-form-item label="相对包路径">
                    <a-input
                        v-model:value="controllerParam.relativePackage"
                        :disabled="!controllerSelcted"
                    />
                </a-form-item>
                <a-form-item label="类名前缀">
                    <a-input
                        v-model:value="controllerParam.classPrefix"
                        :disabled="!controllerSelcted"
                    />
                </a-form-item>
                <a-form-item label="对象名前缀">
                    <a-input
                        v-model:value="controllerParam.objectPrefix"
                        :disabled="!controllerSelcted"
                    />
                </a-form-item>
                <a-form-item label="Model基础包">
                    <a-input
                        v-model:value="controllerParam.modelBasePackage"
                        :disabled="!controllerSelcted"
                    />
                </a-form-item>
                <a-form-item label="Service基础包">
                    <a-input
                        v-model:value="controllerParam.serviceBasePackage"
                        :disabled="!controllerSelcted"
                    />
                </a-form-item>
                <a-form-item label="Api标签">
                    <a-input v-model:value="controllerParam.tag" :disabled="!controllerSelcted" />
                </a-form-item>
                <a-form-item label="Url">
                    <a-input v-model:value="controllerParam.url" :disabled="!controllerSelcted" />
                </a-form-item>
            </a-form>
        </div>
        <a-divider />
        <div>
            <a-checkbox
                :indeterminate="indeterminate"
                :checked="checkAll"
                @change="onChangeCheckAll"
            >全选</a-checkbox>
            <a-divider type="vertical" />
            <a-button
                type="primary"
                :disabled="!indeterminate && !checkAll"
                @click="handleCodeGenerate"
            >生成</a-button>
        </div>
    </a-card>
</template>

<script setup lang="ts">
import { ref, reactive, watch, onMounted } from 'vue';
import { message } from 'ant-design-vue';
import { Bus } from '@/plugin';
// Api
import { ApiCodeGenerator } from '@/axios/api';
// Model
import { Result } from '@/model/common';
import { TemplateParamForm, EntityTemplateParam, EntityField, ModelTemplateParam, DaoTemplateParam, ServiceTemplateParam, ControllerTemplateParam, ManagerTemplateParam } from '@/model/code_generator';

onMounted(() => {
    Bus.on('refresh_db_column', (_param: any) => {
        if (/^sys_/.test(_param.table)) {
            entity.name = _param.table.slice(_param.table.indexOf('_') + 1);
        } else {
            entity.name = _param.table;
        }
    });
    Bus.on('change_selected_db_column', (_param: any) => {
        selectedEntityFields = _param;
    })
})

const entity = reactive(new Entity());
watch(() => entity.name, (value) => {
    entity.className = value.charAt(0).toUpperCase() + value.slice(1);
    entity.objectName = value.charAt(0).toLowerCase() + value.slice(1);
    const nameArr = value.split('');
    let relativePackage = value;
    nameArr.forEach(name => {
        if (/[A-Z]/.test(name)) {
            relativePackage = relativePackage.replace(name, `.${name.toLowerCase()}`);
        }
    })
    if (relativePackage.startsWith('.')) {
        relativePackage = relativePackage.slice(1);
    }
    entity.relativePackage = relativePackage;

    controllerParam.tag = value;
});
watch(() => entity.projectPath, (value) => {
    entityParam.projectPath = value;
    modelParam.projectPath = value;
    daoParam.projectPath = value;
    managerParam.projectPath = value;
    serviceParam.projectPath = value;
    controllerParam.projectPath = value;
});
watch(() => entity.className, (value) => {
    entityParam.classPrefix = value;
    modelParam.classPrefix = value;
    daoParam.classPrefix = value;
    managerParam.classPrefix = value;
    serviceParam.classPrefix = value;
    controllerParam.classPrefix = value;
});
watch(() => entity.objectName, (value) => {
    modelParam.objectPrefix = value;
    managerParam.objectPrefix = value;
    serviceParam.objectPrefix = value;
    controllerParam.objectPrefix = value;
});
watch(() => entity.relativePackage, (value) => {
    entityParam.relativePackage = value;
    modelParam.relativePackage = value;
    daoParam.relativePackage = value;
    managerParam.relativePackage = value;
    serviceParam.relativePackage = value;
    controllerParam.relativePackage = value;
    controllerParam.url = value.replaceAll('.', "/");
});

// 列表中选择的实体字段
let selectedEntityFields: EntityField[] = [];
const entitySelected = ref(false);
const entityParam = reactive(new EntityTemplateParam());
const modelSelected = ref(false);
const modelParam = reactive(new ModelTemplateParam());
const daoSelected = ref(false);
const daoParam = reactive(new DaoTemplateParam());
const managerSelected = ref(false);
const managerParam = reactive(new ManagerTemplateParam());
const serviceSelected = ref(false);
const serviceParam = reactive(new ServiceTemplateParam());
const controllerSelcted = ref(false);
const controllerParam = reactive(new ControllerTemplateParam());

watch(() => entityParam.entityBasePackage, (value) => {
    modelParam.entityBasePackage = value;
    daoParam.entityBasePackage = value;
    serviceParam.entityBasePackage = value;
    controllerParam.entityBasePackage = value;
})

watch(() => modelParam.modelBasePackage, (value) => {
    daoParam.modelBasePackage = value;
    serviceParam.modelBasePackage = value;
    controllerParam.modelBasePackage = value;
})

watch(() => daoParam.daoBasePackage, (value) => {
    serviceParam.daoBasePackage = value;
    managerParam.daoBasePackage = value;
})

watch(() => serviceParam.serviceBasePackage, (value) => {
    controllerParam.serviceBasePackage = value;
})

const indeterminate = ref(false);
const checkAll = ref(false);

watch([entitySelected, modelSelected, daoSelected, serviceSelected, controllerSelcted], (value) => {
    if (value.includes(true) && !value.includes(false)) {
        indeterminate.value = false;
        checkAll.value = true;
    } else if (value.includes(true)) {
        indeterminate.value = true;
        checkAll.value = false;
    } else {
        indeterminate.value = false;
        checkAll.value = false;
    }
})

const onChangeCheckAll = (event: Event) => {
    const checked = (event.target as any).checked;
    entitySelected.value = checked;
    modelSelected.value = checked;
    daoSelected.value = checked;
    managerSelected.value = checked;
    serviceSelected.value = checked;
    controllerSelcted.value = checked;
}

const handleCodeGenerate = () => {
    const form = new TemplateParamForm();
    // Entity
    form.entityParam = entitySelected.value ? entityParam : undefined;
    if (form.entityParam) {
        form.entityParam.fieldList = selectedEntityFields;
    }
    // Model
    form.modelParam = modelSelected.value ? modelParam : undefined;
    if (form.modelParam) {
        form.modelParam.fieldList = selectedEntityFields;
    }
    // Dao
    form.daoParam = daoSelected.value ? daoParam : undefined;
    // Manager
    form.managerParam = managerSelected.value ? managerParam : undefined;
    // Service
    form.serviceParam = serviceSelected.value ? serviceParam : undefined;
    // Controller
    form.controllerParam = controllerSelcted.value ? controllerParam : undefined;
    ApiCodeGenerator.codeGenerate(form)
        .then(() => {
            message.success('代码生成成功！');
        })
        .catch((err: Result) => {
            message.error(`代码生成失败！${err.msg}`);
        })
}

</script>

<script lang="ts">
export class Entity {
    public name!: string;
    public className!: string;
    public objectName!: string;
    public relativePackage!: string;
    // public projectPath!: string;
    public projectPath = 'F:/Code/Company/2021_registration_sys/service/';
}
</script>

<style lang="less" scoped>
.code_layer {
    .ant-form {
        &:last-child {
            margin-bottom: -16px;
        }
        .ant-form-item {
            margin-bottom: 16px;

            &:first-child {
                width: 120px;
            }
        }
    }
}
</style>